namespace SaToken.SaToken.Session;

/// <summary>
/// 登录设备终端信息 Model
/// </summary>
[Serializable]
public class SaTerminalInfo
{

    /// <summary>
    /// 登录会话索引值 (该账号第几个登录的设备, 从 1 开始)
    /// </summary>
    private int _index;

    /// <summary>
    /// Token 值
    /// </summary>
    private string _tokenValue;

    /// <summary>
    /// 所属设备类型，例如：PC、WEB、HD、MOBILE、APP
    /// </summary>
    private string _deviceType;

    /// <summary>
    /// 登录设备唯一标识，例如：kQwIOrYvnXmSDkwEiFngrKidMcdrgKorXmSDkwEiFngrKidM
    /// </summary>
    private string _deviceId;

    /// <summary>
    /// 此次登录的自定义扩展数据 (只允许在登录前设定，登录后不建议更改)
    /// </summary>
    private Dictionary<string, object> _extraData;

    /// <summary>
    /// 创建时间
    /// </summary>
    private long _createTime;

    /// <summary>
    /// 构建一个空的 SaTerminalInfo
    /// </summary>
    public SaTerminalInfo()
    {
    }

    /// <summary>
    /// 构建一个 SaTerminalInfo
    /// </summary>
    /// <param name="index">登录会话索引值 (该账号第几个登录的设备)</param>
    /// <param name="tokenValue">Token 值</param>
    /// <param name="deviceType">所属设备类型</param>
    /// <param name="extraData">此客户端登录的挂载数据</param>
    public SaTerminalInfo(int index, string tokenValue, string deviceType, Dictionary<string, object> extraData)
    {
        _index = index;
        _tokenValue = tokenValue;
        _deviceType = deviceType;
        _extraData = extraData;
        _createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
    }

    // 扩展方法

    /// <summary>
    /// 设置此次登录的自定义扩展数据 (只允许在登录前设定，登录后不建议更改)
    /// </summary>
    /// <param name="key">键</param>
    /// <param name="value">值</param>
    /// <returns>对象自身</returns>
    public SaTerminalInfo SetExtra(string key, object value)
    {
        if (_extraData == null)
        {
            _extraData = new Dictionary<string, object>();
        }

        _extraData[key] = value;
        return this;
    }

    /// <summary>
    /// 获取此次登录的自定义扩展数据
    /// </summary>
    /// <param name="key">键</param>
    /// <returns>扩展数据的值</returns>
    public object GetExtra(string key)
    {
        if (_extraData == null)
        {
            return null;
        }

        _extraData.TryGetValue(key, out object value);
        return value;
    }

    /// <summary>
    /// 判断是否设置了扩展数据
    /// </summary>
    /// <returns>是否有扩展数据</returns>
    public bool HaveExtraData()
    {
        return _extraData != null && _extraData.Count > 0;
    }

    // -------------------- Get/Set 方法 --------------------

    /// <summary>
    /// 获取登录会话索引值 (该账号第几个登录的设备)
    /// </summary>
    /// <returns>登录会话索引值</returns>
    public int GetIndex()
    {
        return _index;
    }

    /// <summary>
    /// 设置登录会话索引值 (该账号第几个登录的设备)
    /// </summary>
    /// <param name="index">登录会话索引值</param>
    /// <returns>对象自身</returns>
    public SaTerminalInfo SetIndex(int index)
    {
        _index = index;
        return this;
    }

    /// <summary>
    /// 获取 Token 值
    /// </summary>
    /// <returns>Token 值</returns>
    public string GetTokenValue()
    {
        return _tokenValue;
    }

    /// <summary>
    /// 设置 Token 值
    /// </summary>
    /// <param name="tokenValue">Token 值</param>
    /// <returns>对象自身</returns>
    public SaTerminalInfo SetTokenValue(string tokenValue)
    {
        _tokenValue = tokenValue;
        return this;
    }

    /// <summary>
    /// 获取所属设备类型
    /// </summary>
    /// <returns>所属设备类型</returns>
    public string GetDeviceType()
    {
        return _deviceType;
    }

    /// <summary>
    /// 设置所属设备类型
    /// </summary>
    /// <param name="deviceType">所属设备类型</param>
    /// <returns>对象自身</returns>
    public SaTerminalInfo SetDeviceType(string deviceType)
    {
        _deviceType = deviceType;
        return this;
    }

    /// <summary>
    /// 获取登录设备唯一标识
    /// </summary>
    /// <returns>登录设备唯一标识</returns>
    public string GetDeviceId()
    {
        return _deviceId;
    }

    /// <summary>
    /// 设置登录设备唯一标识
    /// </summary>
    /// <param name="deviceId">登录设备唯一标识，例如：kQwIOrYvnXmSDkwEiFngrKidMcdrgKorXmSDkwEiFngrKidM</param>
    /// <returns>对象自身</returns>
    public SaTerminalInfo SetDeviceId(string deviceId)
    {
        _deviceId = deviceId;
        return this;
    }

    /// <summary>
    /// 获取此客户端登录的挂载数据
    /// </summary>
    /// <returns>挂载数据</returns>
    public Dictionary<string, object> GetExtraData()
    {
        return _extraData;
    }

    /// <summary>
    /// 设置此客户端登录的挂载数据
    /// </summary>
    /// <param name="extraData">挂载数据</param>
    /// <returns>对象自身</returns>
    public SaTerminalInfo SetExtraData(Dictionary<string, object> extraData)
    {
        _extraData = extraData;
        return this;
    }

    /// <summary>
    /// 获取创建时间
    /// </summary>
    /// <returns>创建时间（13位时间戳）</returns>
    public long GetCreateTime()
    {
        return _createTime;
    }

    /// <summary>
    /// 设置创建时间
    /// </summary>
    /// <param name="createTime">创建时间（13位时间戳）</param>
    /// <returns>对象自身</returns>
    public SaTerminalInfo SetCreateTime(long createTime)
    {
        _createTime = createTime;
        return this;
    }

    /// <summary>
    /// 转换为字符串表示
    /// </summary>
    /// <returns>字符串表示</returns>
    public override string ToString()
    {
        return
            $"SaTerminalInfo [index={_index}, tokenValue='{_tokenValue}', deviceType='{_deviceType}', deviceId='{_deviceId}', extraData={ExtraDataToString()}, createTime={_createTime}]";
    }

    /// <summary>
    /// 辅助方法：将extraData转换为字符串
    /// </summary>
    private string ExtraDataToString()
    {
        if (_extraData == null)
        {
            return "null";
        }

        var items = _extraData.Select(pair => $"{pair.Key}={pair.Value}").ToList();

        return "{" + string.Join(", ", items) + "}";
    }
}